当你需要将Git项目迁移到新位置、更换托管平台或彻底重置版本控制时,就很有可能需要这些知识。

项目迁移的需求比你想的要常见得多。比如你从 GitHub 搬到公司内网的 GitLab,或者将旧项目里的子模块拆分成独立服务,甚至是因为一不小心把密钥上传了,想清理历史记录重开一个干净的新仓库。这些场景下,你就需要用对 Git 的“迁移姿势”。
很多开发者觉得迁移麻烦,其实只要理解 Git 本质上是一个内容寻址的“版本快照系统”,你就会发现迁移不外乎两件事:“我要保留什么?”、“我要丢弃什么?”这篇指南就是围绕这两个问题展开,让你从容应对各种 Git 迁移需求。

对了,你可以根据下面的决策树,决定你想阅读的部分,实践过程中有疑问欢迎探讨。

迁移决策树
保留历史? → 用--mirror克隆
只需最新代码? → 移除.git后重建
需要部分历史? → git filter-repo

完整迁移方案(保留历史记录)

如果你想把整个仓库搬家,不想丢掉任何东西(包括分支、Tag、历史提交、远程设置等),--mirror 是你最好的选择。它就像一张完整备份快照,把 .git 中的所有引用和配置都复制一份,适合对原始仓库做“全量克隆”。
这个方法尤其适合从一个平台搬到另一个平台,比如从 GitHub 搬到 Gitee 或 GitLab。注意,推送时也要用 --mirror,否则有些引用(如远程分支)不会同步过去。如果原项目的默认分支是 master,而新仓库默认使用 main,也可以中途重命名。总之,这种方法是最“保险”的迁移方式,适合保守型开发者。

1
2
3
4
5
6
7
8
9
10
# 1. 克隆原仓库(保留所有分支和标签)
git clone --mirror https://github.com/user/old-repo.git
cd old-repo.git

# 2. 推送到新仓库
git push --mirror https://gitee.com/user/new-repo.git

# 3. 本地切换新源(适用于已有工作区)
git remote set-url origin https://new-repo-url.git
git push -u origin --all

纯净迁移方案(不保留历史)

有时候,我们并不想背着历史包袱重新开始,尤其是当你意识到旧代码已经乱成一团,或者包含了不该泄露的敏感信息。这时,你可以选择删除 .git 目录后重建仓库。这种方式非常直接粗暴,也非常“轻量”:只保留代码内容,丢掉所有版本历史,就像从来没用过 Git 一样重新开始。
当然,这种方法的风险也在于你将彻底丢失所有变更记录、作者信息和 Tag。所以如果是团队项目,建议先沟通好再操作。如果你想只保留某一分支最近的提交,也可以用 git clone --depth 1 进行浅克隆,然后重新初始化。

1
2
3
4
5
6
7
8
9
10
11
# 1. 解除当前版本控制(保留文件)
rm -rf .git

# 2. 初始化新仓库
git init
git add .
git commit -m "初始提交"

# 3. 关联远程仓库
git remote add origin https://new-repo-url.git
git push -u origin master

高级迁移技巧

大型单体仓库逐渐拆分成微服务或子模块,是很多团队发展的必经阶段。这时候你可能就会想:我只关心某个子目录的内容,能不能把它独立成一个仓库,还保留它的提交历史?当然可以,这就要用上 Git 高级利器 —— git filter-repo
filter-repo 可以非常高效地把某个目录及其历史提交“提取”出来,形成一个全新的独立仓库,不仅文件内容干净,连提交记录都只保留相关部分。比如把 src/module-a 提成一个新仓库,并作为根目录使用,就可以用 --subdirectory-filter。它的效果比 filter-branch 快百倍,也更不容易出错。唯一要注意的是,它需要额外安装,建议在克隆出来的副本里操作,避免污染原始仓库。

  1. 迁移指定分支

    1
    git push new_remote local_branch:remote_branch
  2. 迁移子目录

    1
    git filter-repo --subdirectory-filter my-subdir
  3. 清理历史大文件

    1
    git filter-repo --strip-blobs-bigger-than 10M

迁移后必检项

  1. 验证分支/标签是否完整:

    1
    git branch -a && git tag -l
  2. 检查文件完整性:

    1
    git fsck --full
  3. 更新CI/CD配置:

    • Jenkins/GitLab CI中的仓库地址
    • Webhook设置

避坑指南

⚠️ 敏感信息处理
迁移前使用git secret scan扫描密钥/密码
推荐工具:git-secrets

⚠️ LF/CRLF问题
这是 Git 世界里最容易被忽略、却最容易“把人整崩溃”的问题之一。如果你在 Mac 上开发,换行符是 LF,而 Windows 默认是 CRLF。于是你 clone 一份代码,结果一提交,全仓库变成了“修改”状态,其实只是换行不一致。
为了避免这种尴尬情况,Git 提供了 core.autocrlf 设置。Windows 用户推荐设置为 true,它会在 checkout 时把 LF 转成 CRLF,提交时再转回;macOS/Linux 用户建议设置为 input,提交时强转 LF,保持一致。除此之外,还建议在仓库根目录建一个 .gitattributes 文件,强制设置文件类型的换行行为。统一格式不仅能避免多人协作混乱,还能让你在 PR、diff 中更容易看出实际修改。

Windows用户迁移后执行:

1
2
git config core.autocrlf input
git reset --hard

⚠️ 高危警告(使用前必读)

你知道吗?全球有数以万计的 Git 仓库曾经不小心泄露了密钥、数据库密码甚至生产环境的 API token。别以为“只是试试”,Git 会把你每一次 commit 的文件都记录在历史中,即使后面删除,历史里也还在。
为了防止“祸从提交起”,推荐在迁移前使用安全扫描工具:AWS 出品的 git-secrets 可以在你提交前实时检测敏感关键词,truffleHog 更是“暴力搜索”连编码过的 token 都能挖出来。如果发现确有泄露,可以配合 filter-repo 清除掉对应的文件和提交。这一步虽然繁琐,却能挽救整个项目的安全风险,强烈建议纳入你团队的代码审查流程中。

  1. 永久性删除

    1
    2
    - 所有提交历史、分支、标签将被不可恢复地删除!
    - 操作前请确认已备份重要版本信息
  2. 作用范围

    1
    2
    + 仅在当前执行目录及其子目录生效
    - 禁止在根目录(/)或家目录(~)运行!可能导致系统崩溃!
  3. 敏感操作防护

    1
    2
    3
    4
    # 安全建议:先预览将被删除的目录
    find . -type d -name ".git" | while read dir; do
    echo "[高危] 即将删除: ${dir}"
    done

附录:补充一个删除.git的安全方案(纯净版)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash

TARGET_DIR=$(pwd)
CONFIRM=""

# 危险操作二次确认
read -p "⚠️ 即将永久删除 ${TARGET_DIR} 下所有.git目录!确认执行?(y/N) " CONFIRM

if [[ $CONFIRM == "y" || $CONFIRM == "Y" ]]; then
echo "[安全日志] 用户确认执行删除操作"
find . -type d -name ".git" -exec echo "删除: {}" \; -exec rm -rf {} +
echo "操作完成 | 删除时间: $(date)"
else
echo "操作已取消"
fi

最后,请务必需要注意,任何删除操作前,用git bundle创建完整备份包,可通过git clone backup.bundle恢复历史**